home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC]
/
NeXTSTEP 3.3 Dev Intel.iso
/
NextDeveloper
/
Source
/
GNU
/
cctools
/
as
/
as.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-03
|
14KB
|
517 lines
/* as.c - GAS main program.
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Main program for AS; a 32-bit assembler of GNU.
* Understands command arguments.
* Has a few routines that don't fit in other modules because they
* are shared.
*
*
* bugs
*
* : initialisers
* Since no-one else says they will support them in future: I
* don't support them now.
*
*/
#include <signal.h>
#include <string.h>
#include "as.h"
#include "input-scrub.h"
#include "symbols.h"
#include "sections.h"
#include "read.h"
#include "md.h"
#include "messages.h"
#include "xmalloc.h"
#include "layout.h"
#include "write_object.h"
/* ['x'] TRUE if "-x" seen. */
char flagseen[128] = { 0 };
/* TRUE if -force_cpusubtype_ALL is specified */
int force_cpusubtype_ALL = 0;
/* set to the corresponding cpusubtype if -arch flag is specified */
cpu_subtype_t archflag_cpusubtype = -1;
/*
* .include "file" looks in source file dir, then stack.
* -I directories are added to the end, then the defaults are added.
*/
struct directory_stack include_defaults[] = {
{ 0, "/NextDeveloper/Headers/" },
{ 0, "/LocalDeveloper/Headers/" },
{ 0, NULL }
};
struct directory_stack *include = NULL; /* First dir to search */
static struct directory_stack *include_tail = NULL; /* Last in chain */
/* next_version is in next_version.c which is created by the Makefile */
extern char next_version[];
/* this is only used here, thus defined here (was in version.c in GAS) */
static char version_string[] = "GNU assembler version 1.38\n";
/*
* The list of signals to catch if not ignored.
*/
static int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
static void got_sig(
int sig);
static void perform_an_assembly_pass(
int argc,
char **argv);
void
main(
int argc,
char **argv,
char **envp)
{
char *progname; /* argv[0] */
int work_argc; /* variable copy of argc */
char **work_argv; /* variable copy of argv */
char *arg; /* an arg to program */
char a; /* an arg flag (after -) */
char *out_file_name;/* name of object file, argument to -o if specified */
int i;
char *specific_archflag;
struct directory_stack *dirtmp;
progname = argv[0];
/*
* Set up to catch the signals listed in sig[] that are not ignored.
*/
for(i = 0; sig[i] != 0; i++)
if(signal(sig[i], SIG_IGN) != SIG_IGN)
signal(sig[i], got_sig);
/*
* Set the default for the flags that will be parsed.
*/
memset(flagseen, '\0', sizeof(flagseen)); /* aint seen nothing yet */
specific_archflag = NULL;
out_file_name = "a.out"; /* default .o file */
/*
* Call the initialization routines.
*/
check_for_ProjectBuilder(); /* messages.c */
symbol_begin(); /* symbols.c */
sections_begin(); /* sections.c */
read_begin(); /* read.c */
md_begin(); /* MACHINE.c */
input_scrub_begin(); /* input_scrub.c */
/*
* Parse arguments, but we are only interested in flags.
* When we find a flag, we process it then make it's argv[] NULL.
* This helps any future argv[] scanners avoid what we processed.
* Since it is easy to do here we interpret the special arg "-"
* to mean "use stdin" and we set that argv[] pointing to "".
* After we have munged argv[], the only things left are source file
* name(s) and ""(s) denoting stdin. These file names are used
* (perhaps more than once) later.
*/
work_argc = argc - 1; /* don't count argv[0] */
work_argv = argv + 1; /* skip argv[0] */
for( ; work_argc-- ; work_argv++){
/* work_argv points to this argument */
arg = *work_argv;
/* Filename. We need it later. */
if(*arg != '-')
continue;
/* Keep scanning args looking for flags. */
if (arg[1] == '-' && arg[2] == 0) {
/* "--" as an argument means read STDIN */
/* on this scan, we don't want to think about filenames */
*work_argv = ""; /* Code that means 'use stdin'. */
continue;
}
/* This better be a switch ( -l where l is a letter. */
arg++; /* -> letter. */
/* scan all the 1-char flags */
while((a = *arg)){
arg ++; /* arg -> after letter. */
a &= 0x7F; /* ascii only please */
if(flagseen[(int)a] && (a != 'I') && (a != 'a') && (a != 'f'))
as_warn("%s: Flag option -%c has already been seen!",
progname, a);
if(a != 'f')
flagseen[(int)a] = TRUE;
switch(a){
case 'f':
if(strcmp(arg-1, "force_cpusubtype_ALL") == 0){
force_cpusubtype_ALL = 1;
arg = ""; /* Finished with this arg. */
break;
}
/* -f means fast - no need for "app" preprocessor. */
flagseen[(int)a] = TRUE;
break;
case 'L': /* -L means keep L* symbols */
break;
case 'o':
if(*arg != '\0') /* Rest of argument is object file-name. */
out_file_name = arg;
else if(work_argc){ /* Want next arg for a file-name. */
*work_argv = NULL; /* This is not a file-name. */
work_argc--;
out_file_name = *++work_argv;
}
else
as_warn("%s: I expected a filename after -o. \"%s\" "
"assumed.", progname, out_file_name);
arg = ""; /* Finished with this arg. */
break;
case 'R':
/* -R means put data into text segment */
as_warn("%s: -R option not supported (use the "
".const directive)", progname);
flagseen['R'] = FALSE;
break;
case 'v':
fprintf(stderr,"NeXT Computer, Inc. version "
"%s, ", next_version);
fprintf(stderr, version_string);
if(*arg && strcmp(arg,"ersion"))
as_warn("Unknown -v option ignored");
while(*arg)
arg++; /* Skip the rest */
break;
case 'W':
/* -W means don't warn about things */
break;
case 'I':
/* Add directory to path for includes */
dirtmp = (struct directory_stack *)
xmalloc(sizeof(struct directory_stack));
/* New one goes on the end */
dirtmp->next = 0;
if(include == 0)
include = dirtmp;
else
include_tail->next = dirtmp;
/* Tail follows the last one */
include_tail = dirtmp;
/* Rest of argument is include file-name. */
if(*arg)
dirtmp->fname = arg;
else if (work_argc){
/* Want next arg for a file-name. */
/* This is not a file-name. */
*work_argv = NULL;
work_argc--;
dirtmp->fname = *++work_argv;
}
else
as_warn("I expected a filename after -I.");
arg = ""; /* Finished with this arg. */
break;
case 'g':
/* generate stabs for debugging assembly code */
break;
case 'n':
/* no default .text section */
break;
case 'd':
if(strcmp(arg-1, "dynamic") == 0){
arg = ""; /* Finished with this arg. */
flagseen[(int)'k'] = TRUE;
break;
}
goto unknown_flag;
case 's':
if(strcmp(arg-1, "static") == 0){
arg = ""; /* Finished with this arg. */
flagseen[(int)'k'] = FALSE;
break;
}
goto unknown_flag;
case 'N':
if(strcmp(arg-1, "NEXTSTEP-deployment-target") == 0){
arg = ""; /* Finished with this arg. */
/* Want next arg for a <release_tag> */
if(work_argc){
/* This, "-NEXTST..." is not a file-name. */
*work_argv = NULL;
work_argc--;
work_argv++;
if(strcmp(*work_argv, "3.3") == 0){
flagseen[(int)'k'] = TRUE;
}
else if(strcmp(*work_argv, "3.2") == 0){
flagseen[(int)'k'] = FALSE;
}
else{
as_fatal("I expected '3.2' or '3.3' after "
"-NEXTSTEP-deployment-target.");
}
}
else
as_fatal("I expected a <release_tag> "
"after -NEXTSTEP-deployment-target.");
break;
}
goto unknown_flag;
case 'k':
/* use new features incompatible with 3.2 */
break;
case 'V':
/* as driver's -V, verbose, flag */
break;
case 'a':
if(strcmp(arg-1, "arch_multiple") == 0){
arch_multiple = 1;
arg = ""; /* Finished with this arg. */
break;
}
else if(strcmp(arg-1, "arch") == 0){
arg = ""; /* Finished with this arg. */
/* Want next arg for a <arch_type> */
if(work_argc){
/* This, "-arch" is not a file-name. */
*work_argv = NULL;
work_argc--;
work_argv++;
#ifdef M68K
if(strcmp(*work_argv, "m68030") == 0){
if(archflag_cpusubtype != -1 &&
archflag_cpusubtype !=
CPU_SUBTYPE_MC68030_ONLY)
as_fatal("can't specify both "
"-arch m68030 and -arch "
"m68040");
specific_archflag = *work_argv;
archflag_cpusubtype =
CPU_SUBTYPE_MC68030_ONLY;
}
else if(strcmp(*work_argv,
"m68040") == 0){
if(archflag_cpusubtype != -1 &&
archflag_cpusubtype !=
CPU_SUBTYPE_MC68040)
as_fatal("can't specify both "
"-arch m68030 and -arch "
"m68040");
specific_archflag = *work_argv;
archflag_cpusubtype =
CPU_SUBTYPE_MC68040;
}
else if(strcmp(*work_argv, "m68k") != 0)
as_fatal("I expected 'm68k', "
"'m68030' or 'm68040' after "
"-arch for this assembler.");
#endif
#ifdef M88K
if(strcmp(*work_argv, "m88k") != 0)
as_fatal("I expected 'm88k' after "
"-arch for this assembler.");
#endif
#ifdef I860
if(strcmp(*work_argv, "i860") != 0)
as_fatal("I expected 'i860' after "
"-arch for this assembler.");
#endif
#ifdef I386
if(strcmp(*work_argv, "i486") == 0){
if(archflag_cpusubtype != -1 &&
archflag_cpusubtype !=
CPU_SUBTYPE_486)
as_fatal("can't specify more "
"than one -arch flag ");
specific_archflag = *work_argv;
archflag_cpusubtype =
CPU_SUBTYPE_486;
}
else if(strcmp(*work_argv,
"i486SX") == 0){
if(archflag_cpusubtype != -1 &&
archflag_cpusubtype !=
CPU_SUBTYPE_486SX)
as_fatal("can't specify more "
"than one -arch flag ");
specific_archflag = *work_argv;
archflag_cpusubtype =
CPU_SUBTYPE_486SX;
}
else if(strcmp(*work_argv, "i586") ==0){
if(archflag_cpusubtype != -1 &&
archflag_cpusubtype !=
CPU_SUBTYPE_586)
as_fatal("can't specify more "
"than one -arch flag ");
specific_archflag = *work_argv;
archflag_cpusubtype =
CPU_SUBTYPE_586;
}
else if(strcmp(*work_argv,
"i586SX") == 0){
if(archflag_cpusubtype != -1 &&
archflag_cpusubtype !=
CPU_SUBTYPE_586SX)
as_fatal("can't specify more "
"than one -arch flag ");
specific_archflag = *work_argv;
archflag_cpusubtype =
CPU_SUBTYPE_586SX;
}
else if(strcmp(*work_argv, "i386") != 0)
as_fatal("I expected 'i386', 'i486'"
" 'i486SX', 'i586' or 'i586SX' "
"after -arch for this "
"assembler.");
#endif
#ifdef HPPA
if(strcmp(*work_argv, "hppa") != 0)
as_fatal("I expected 'hppa' after "
"-arch for this assembler.");
#endif
#ifdef SPARC
if(strcmp(*work_argv, "sparc") != 0)
as_fatal("I expected 'sparc' after "
"-arch for this assembler.");
#endif
}
else
as_fatal("I expected an <arch_type> "
"after -arch.");
break;
}
/* fall through for non -arch flag */
default:
unknown_flag:
--arg;
if(md_parse_option(&arg, &work_argc, &work_argv) == 0)
as_warn("%s: I don't understand '%c' flag!", progname,
a);
if(arg && *arg)
arg++;
break;
}
}
/*
* We have just processed a "-..." arg, which was not a
* file-name. Smash it so the
* things that look for filenames won't ever see it.
*
* Whatever work_argv points to, it has already been used
* as part of a flag, so DON'T re-use it as a filename.
*/
*work_argv = NULL; /* NULL means 'not a file-name' */
}
if(flagseen['g'] == TRUE && flagseen['n'] == TRUE)
as_fatal("-g can't be specified if -n is specified");
/*
* If we haven't seen a -force_cpusubtype_ALL or an -arch flag for a
* specific architecture then let the machine instructions in the
* assembly determine the cpusubtype of the output file.
*/
if(force_cpusubtype_ALL && specific_archflag)
archflag_cpusubtype = -1;
/* Here with flags set up in flagseen[]. */
perform_an_assembly_pass(argc, argv); /* Assemble it. */
if(seen_at_least_1_file() && bad_error != TRUE){
layout_addresses();
write_object(out_file_name);
}
input_scrub_end();
md_end(); /* MACHINE.c */
exit(bad_error); /* WIN */
}
/* perform_an_assembly_pass()
*
* Here to attempt 1 pass over each input file.
* We scan argv[*] looking for filenames or exactly "" which is
* shorthand for stdin. Any argv that is NULL is not a file-name.
* We set need_pass_2 TRUE if, after this, we still have unresolved
* expressions of the form (unknown value)+-(unknown value).
*
* Note the un*x semantics: there is only 1 logical input file, but it
* may be a catenation of many 'physical' input files.
*/
static
void
perform_an_assembly_pass(
int argc,
char **argv)
{
char *buffer; /* Where each bufferful of lines will start. */
int saw_a_file;
saw_a_file = 0;
argv++; /* skip argv[0] */
argc--; /* skip argv[0] */
while(argc--){
if(*argv){ /* Is it a file-name argument? */
/* argv -> "" if stdin desired, else -> filename */
if((buffer = input_scrub_new_file(*argv))){
saw_a_file++;
read_a_source_file(buffer);
}
}
argv++; /* completed that argv */
}
if(!saw_a_file)
if((buffer = input_scrub_new_file("")))
read_a_source_file(buffer);
}
static
void
got_sig(
int sig)
{
static int here_before = 0;
as_bad("Interrupted by signal %d",sig);
if(here_before++)
exit(1);
}